﻿using BCAMap.AMap;
using BCCommon;
using BCCommon.TMS.Transport;
using BCData.TMS.Order.Order;
using BCData.TMS.Order.OrderExtention;
using BCData.TMS.Order.OrderMoveHouseSpecificationServiceRecord;
using BCData.TMS.Order.OrderPool;
using BCData.TMS.Order.OrderSpecificServiceRecord;
using BCData.TMS.OrderExtentionGoodsChecklist;
using BCData.TMS.OrderFreightAppendRecord;
using BCData.TMS.OrderFreightFormulaRecord;
using BCData.TMS.OrderFreightRecord;
using BCData.TMS.OrderPackingRecord;
using BCData.TMS.TransportOrder;
using BCData.TMS.VehicleCategoryReference;
using BCDto.TMS.TransportOrder;
using BCEntity.Common.Area;
using BCEntity.Common.EntityNameConst;
using BCEntity.TMS.TransportOrder;
using BCService.Common.Area;
using BCService.CRM.BigCustomer;
using BCService.CRM.BigCustomerFreightConfigExtention;
using BCService.CRM.BigCustomerFreightConfiguration;
using BCService.Sim.Company.Company;
using BCService.SmsService;
using BCService.TMS.Agent.AgentAreaRecord;
using BCService.TMS.Agent.AgentRecord;
using BCService.TMS.EasyMoveSuiteConfig;
using BCService.TMS.Fence;
using BCService.TMS.FreightConfigurationExtention;
using BCService.TMS.FreightConfigurationService;
using BCService.TMS.HorsemanFreightConfiguration;
using BCService.TMS.HorsemanFreightExtention;
using BCService.TMS.InsuredConfig;
using BCService.TMS.MarketingCoupon.MarketingCoupon;
using BCService.TMS.MarketingCoupon.MarketingCouponReceive;
using BCService.TMS.MarketingCoupon.MarketingCouponUsing;
using BCService.TMS.MoveHouseConfig.MoveHouseSpecificationServiceConfig;
using BCService.TMS.NightFreightConfiguration;
using BCService.TMS.Order.Order;
using BCService.TMS.Packing.PackingConfig;
using BCService.TMS.TransportSpecificServiceConfig;
using BCService.TMS.TransportSpecificServiceConfigOverWrite;
using BCService.TMS.VehicleBusinessMappingOverwrite;
using BCService.TMS.VehicleSuiteBusinessConfig;
using BCService.TMS.VehicleTransportBusinessConfig;
using BCService.TMS.VehicleTypeService;
using BCService.TMS.WorkingCompany;
using BCService.TMS.WorryFreeMoveSuiteConfig;
using BCService.Utils;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;

namespace BCService.TMS.TransportOrder
{
    public class TransportOrderService : ITransportOrderService
    {
        private readonly IRedisService redisService;
        private readonly ITransportOrderData transportOrderData;
        private readonly IZoneService zoneService;
        private readonly IConfiguration configuuration;
        private readonly IDatabaseContext databaseContext;
        private readonly ICompanyService companyService;
        private readonly IAgentRecordService agentRecordService;
        private readonly IMarketingCouponService marketingCouponService;
        private readonly IMarketingCouponReceiveService marketingCouponReceiveService;
        private readonly IMarketingCouponUsingService marketingCouponUsingService;
        private readonly IInsuredConfigService insuredConfigService;
        private readonly IOrderData orderData;
        private readonly IOrderExtentionData orderExtentionData;
        private readonly IOrderMoveHouseSpecificationServiceRecordData orderMoveHouseSpecificationServiceRecordData;
        private readonly IOrderSpecificServiceRecordData orderSpecificServiceRecordData;
        private readonly IOrderPoolData orderPoolData;
        private readonly IOrderFreightRecordData orderFreightRecordData;
        private readonly IOrderFreightFormulaRecordData orderFreightFormulaRecordData;
        private readonly IOrderExtentionGoodsChecklistData orderExtentionGoodsChecklistData;
        private readonly IOrderFreightAppendRecordData orderFreightAppendRecordData;
        private readonly IAliyunSmsService aliyunSmsService;
        private readonly string key = string.Format("{0}", EntityNameConst.TransportOrderEntity);
        private readonly IVehicleCategoryReferenceData vehicleCategoryReferenceData;
        private readonly IBigCustomerService bigCustomerService;
        private readonly IBigCustomerFreightConfigurationService bigCustomerFreightConfigurationService;
        private readonly IBigCustomerFreightConfigExtentionService bigCustomerFreightConfigExtentionService;
        public TransportOrderService(
            IRedisService redisService,
            ITransportOrderData transportOrderData,
            IZoneService zoneService,
            IConfiguration configuuration,
            IDatabaseContext databaseContext,
            ICompanyService companyService,
            IAgentRecordService agentRecordService,
            IMarketingCouponService marketingCouponService,
            IMarketingCouponReceiveService marketingCouponReceiveService,
            IMarketingCouponUsingService marketingCouponUsingService,
            IInsuredConfigService insuredConfigService,
            IOrderData orderData,
            IOrderExtentionData orderExtentionData,
            IOrderMoveHouseSpecificationServiceRecordData orderMoveHouseSpecificationServiceRecordData,
            IOrderSpecificServiceRecordData orderSpecificServiceRecordData,
            IOrderPoolData orderPoolData,
            IOrderFreightRecordData orderFreightRecordData,
            IOrderFreightFormulaRecordData orderFreightFormulaRecordData,
            IOrderExtentionGoodsChecklistData orderExtentionGoodsChecklistData,
            IOrderFreightAppendRecordData orderFreightAppendRecordData,
            IAliyunSmsService aliyunSmsService,
            IVehicleCategoryReferenceData vehicleCategoryReferenceData,
            IBigCustomerService bigCustomerService,
            IBigCustomerFreightConfigurationService bigCustomerFreightConfigurationService,
            IBigCustomerFreightConfigExtentionService bigCustomerFreightConfigExtentionService)
        {
            this.redisService = redisService;
            this.transportOrderData = transportOrderData;
            this.zoneService = zoneService;
            this.configuuration = configuuration;
            this.databaseContext = databaseContext;
            this.agentRecordService = agentRecordService;
            this.companyService = companyService;
            this.marketingCouponService = marketingCouponService;
            this.marketingCouponReceiveService = marketingCouponReceiveService;
            this.marketingCouponUsingService = marketingCouponUsingService;
            this.insuredConfigService = insuredConfigService;
            this.orderData = orderData;
            this.orderExtentionData = orderExtentionData;
            this.orderMoveHouseSpecificationServiceRecordData = orderMoveHouseSpecificationServiceRecordData;
            this.orderSpecificServiceRecordData = orderSpecificServiceRecordData;
            this.orderPoolData = orderPoolData;
            this.orderFreightRecordData = orderFreightRecordData;
            this.orderFreightFormulaRecordData = orderFreightFormulaRecordData;
            this.orderExtentionGoodsChecklistData = orderExtentionGoodsChecklistData;
            this.orderFreightAppendRecordData = orderFreightAppendRecordData;
            this.aliyunSmsService = aliyunSmsService;
            this.vehicleCategoryReferenceData = vehicleCategoryReferenceData;
            this.bigCustomerService = bigCustomerService;
            this.bigCustomerFreightConfigurationService = bigCustomerFreightConfigurationService;
            this.bigCustomerFreightConfigExtentionService = bigCustomerFreightConfigExtentionService;
        }
        public IOrderService GetOrderService(TransportBusinessType transportBusinessType, VehicleSuiteBusinessType? vehicleSuiteBusinessType)
        {
            IOrderService orderService;
            IServiceProvider service = GeneralContainer.ServiceProvider;
            IAMapUtils amapUtils = service.GetService<IAMapUtils>();
            IVehicleTransportBusinessConfigService vehicleTransportBusinessConfigService = service.GetService<IVehicleTransportBusinessConfigService>();
            IVehicleBusinessMappingOverwriteService vehicleBusinessMappingOverwriteService = service.GetService<IVehicleBusinessMappingOverwriteService>();
            IVehicleTypeService vehicleTypeService = service.GetService<IVehicleTypeService>();
            IAgentAreaRecordService agentAreaRecordService = service.GetService<IAgentAreaRecordService>();
            ITransportSpecificServiceConfigService transportSpecificServiceConfigService = service.GetService<ITransportSpecificServiceConfigService>();
            ITransportSpecificServiceConfigOverWriteService transportSpecificServiceConfigOverWriteService = service.GetService<ITransportSpecificServiceConfigOverWriteService>();
            switch (transportBusinessType)
            {
                case TransportBusinessType.RunErrands:
                    {
                        IFenceService fenceService = service.GetService<IFenceService>();
                        IHorsemanFreightConfigurationService horsemanFreightConfigurationService = service.GetService<IHorsemanFreightConfigurationService>();
                        IHorsemanFreightExtentionService horsemanFreightExtentionService = service.GetService<IHorsemanFreightExtentionService>();
                        IWorkingCompanyService workingCompanyService = service.GetService<IWorkingCompanyService>();
                        orderService = new RunErrandsOrderService(databaseContext, configuuration, zoneService, amapUtils, companyService, agentRecordService, agentAreaRecordService, this, vehicleTypeService, vehicleTransportBusinessConfigService,
                            vehicleBusinessMappingOverwriteService, marketingCouponService, marketingCouponReceiveService, marketingCouponUsingService, fenceService, workingCompanyService, horsemanFreightConfigurationService, horsemanFreightExtentionService,
                            insuredConfigService, orderData, orderExtentionData, orderPoolData, orderFreightRecordData, orderFreightFormulaRecordData, orderExtentionGoodsChecklistData, orderFreightAppendRecordData, aliyunSmsService);
                        return orderService;
                    }
                case TransportBusinessType.SameCity:
                    {
                        IFreightConfigurationService freightConfigurationService = service.GetService<IFreightConfigurationService>();
                        INightFreightConfigurationService nightFreightConfigurationService = service.GetService<INightFreightConfigurationService>();
                        orderService = new SameCityOrderService(databaseContext, configuuration, zoneService, amapUtils, companyService, agentRecordService, agentAreaRecordService, this, vehicleTransportBusinessConfigService,
                                vehicleBusinessMappingOverwriteService, marketingCouponService, marketingCouponReceiveService, marketingCouponUsingService, freightConfigurationService, nightFreightConfigurationService,
                                insuredConfigService, orderData, orderExtentionData, orderPoolData, orderFreightRecordData, orderFreightFormulaRecordData, orderFreightAppendRecordData,orderExtentionGoodsChecklistData,
                                vehicleCategoryReferenceData, bigCustomerService, bigCustomerFreightConfigurationService);
                        return orderService;
                    }
                case TransportBusinessType.SmallPieces:
                    {
                        IFreightConfigurationExtentionService freightConfigurationExtentionService = service.GetService<IFreightConfigurationExtentionService>();
                        IPackingConfigService packingConfigService = service.GetService<IPackingConfigService>();
                        IOrderPackingRecordData orderPackingRecordData = service.GetService<IOrderPackingRecordData>();
                        orderService = new SmallPiecesOrderService(databaseContext, configuuration, zoneService, amapUtils, companyService, agentRecordService, agentAreaRecordService, this, vehicleTransportBusinessConfigService,
                                vehicleBusinessMappingOverwriteService, vehicleTypeService, marketingCouponService, marketingCouponReceiveService, marketingCouponUsingService, freightConfigurationExtentionService,
                                insuredConfigService, packingConfigService, orderData, orderExtentionData, orderPackingRecordData, orderPoolData, orderFreightRecordData, orderFreightFormulaRecordData, orderExtentionGoodsChecklistData,
                                orderFreightAppendRecordData, bigCustomerService, bigCustomerFreightConfigExtentionService);
                        return orderService;
                    }
                default:
                    {
                        IFreightConfigurationService freightConfigurationService = service.GetService<IFreightConfigurationService>();
                        INightFreightConfigurationService nightFreightConfigurationService = service.GetService<INightFreightConfigurationService>();
                        IVehicleSuiteBusinessConfigService vehicleSuiteBusinessConfigService = service.GetService<IVehicleSuiteBusinessConfigService>();

                        if (!vehicleSuiteBusinessType.HasValue)
                        {
                            throw new ArgumentException("未指定套餐业务类型，无法计算!");
                        }
                        if (vehicleSuiteBusinessType.Value == VehicleSuiteBusinessType.EasyMove)
                        {
                            IEasyMoveSuiteConfigService easyMoveSuiteConfigService = service.GetService<IEasyMoveSuiteConfigService>();

                            orderService = new EasyMoveSuiteOrderService(databaseContext, configuuration, zoneService, amapUtils, companyService, agentRecordService, agentAreaRecordService, this, vehicleTransportBusinessConfigService,
                                vehicleBusinessMappingOverwriteService, vehicleSuiteBusinessConfigService, marketingCouponService, marketingCouponReceiveService, marketingCouponUsingService, vehicleTypeService, easyMoveSuiteConfigService, 
                                freightConfigurationService, nightFreightConfigurationService, transportSpecificServiceConfigOverWriteService, transportSpecificServiceConfigService, insuredConfigService, orderData, 
                                orderExtentionData, orderSpecificServiceRecordData, orderPoolData, orderFreightRecordData, orderFreightFormulaRecordData, vehicleCategoryReferenceData, orderFreightAppendRecordData);
                        }
                        else
                        {
                            IWorryFreeMoveSuiteConfigService worryFreeMoveSuiteConfigService = service.GetService<IWorryFreeMoveSuiteConfigService>();
                            IMoveHouseSpecificationServiceConfigOverWriteService moveHouseSpecificationServiceConfigOverWriteService = service.GetService<IMoveHouseSpecificationServiceConfigOverWriteService>();
                            IMoveHouseSpecificationServiceConfigService moveHouseSpecificationServiceConfigService = service.GetService<IMoveHouseSpecificationServiceConfigService>();

                            orderService = new WorryFreeMoveSuiteOrderService(databaseContext, configuuration, zoneService, amapUtils, companyService, agentRecordService, agentAreaRecordService, this, vehicleTransportBusinessConfigService,
                                vehicleBusinessMappingOverwriteService, marketingCouponService, marketingCouponReceiveService, marketingCouponUsingService, vehicleTypeService, vehicleSuiteBusinessConfigService, worryFreeMoveSuiteConfigService, 
                                freightConfigurationService, nightFreightConfigurationService, moveHouseSpecificationServiceConfigService, moveHouseSpecificationServiceConfigOverWriteService, insuredConfigService, orderData, 
                                orderExtentionData, orderMoveHouseSpecificationServiceRecordData, orderSpecificServiceRecordData, orderPoolData, orderFreightRecordData, orderFreightFormulaRecordData, 
                                transportSpecificServiceConfigOverWriteService, transportSpecificServiceConfigService);
                        }
                        return orderService;
                    }
            }

        }

        #region 检查运输订单是否存在
        public bool Exists(long transportOrderId)
        {
            return this.transportOrderData.Exists(transportOrderId).GetAwaiter().GetResult();
        }
        #endregion

        #region 添加运输订单
        public TransportOrderDto Add(TransportOrderRequestDto requestDto)
        {
            var entity = requestDto.As<TransportOrderEntity>();
            ZoneEntity zoneEntity = this.zoneService.GetFromZoneEntity(entity.CountyCode);
            if (zoneEntity == null || zoneEntity.provinceEntity == null || zoneEntity.cityEntity == null || zoneEntity.countyEntity == null)
            {
                throw new ArgumentException("地址未能匹配到正确的地址信息，请联系客服");
            }
            ZoneEntity endZoneEntity = this.zoneService.GetFromZoneEntity(entity.EndCountyCode);
            if (endZoneEntity == null || endZoneEntity.provinceEntity == null || endZoneEntity.cityEntity == null || endZoneEntity.countyEntity == null)
            {
                throw new ArgumentException("地址未能匹配到正确的地址信息，请联系客服");
            }
            entity.ProvinceCode = zoneEntity.provinceEntity.ProvinceCode;
            entity.CityCode = zoneEntity.cityEntity.CityCode;
            entity.CountyCode = zoneEntity.countyEntity.CountyCode;
            entity.ProvinceName = zoneEntity.provinceEntity.ProvinceName;
            entity.CityName = zoneEntity.cityEntity.CityName;
            entity.CountyName = zoneEntity.countyEntity.CountyName;
            entity.EndProvinceCode = endZoneEntity.provinceEntity.ProvinceCode;
            entity.EndCityCode = endZoneEntity.cityEntity.CityCode;
            entity.EndCountyCode = endZoneEntity.countyEntity.CountyCode;
            entity.EndProvinceName = endZoneEntity.provinceEntity.ProvinceName;
            entity.EndCityName = endZoneEntity.cityEntity.CityName;
            entity.EndCountyName = endZoneEntity.countyEntity.CountyName;
            return this.transportOrderData.Add(entity).GetAwaiter().GetResult().As<TransportOrderDto>();
        }
        #endregion

        #region 修改运输订单
        public TransportOrderDto Update(TransportOrderPutDto putDto)
        {
            if (!this.Exists(putDto.TransportOrderId))
            {
                throw new ArgumentException("此记录不存在!");
            }
            var entity = putDto.As<TransportOrderEntity>();
            var result = this.transportOrderData.Update(entity).GetAwaiter().GetResult().As<TransportOrderDto>();
            string cacheKey = this.redisService.GetKey(key, entity.TransportOrderId);
            this.redisService.DeleteAsync(cacheKey);
            return result;
        }
        #endregion

        #region 删除运输订单
        public bool Delete(long transportOrderId)
        {
            if (!this.Exists(transportOrderId))
            {
                throw new ArgumentException("此记录不存在!");
            }

            var result = this.transportOrderData.Delete(transportOrderId).GetAwaiter().GetResult();
            string cacheKey = this.redisService.GetKey(key, transportOrderId);
            this.redisService.DeleteAsync(cacheKey);
            return result;
        }
        #endregion

        #region 获取运输订单
        public TransportOrderDto Get(long transportOrderId)
        {
            string cacheKey = this.redisService.GetKey(key, transportOrderId);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var data = this.transportOrderData.GetEntity(transportOrderId).GetAwaiter().GetResult();
                return data;
            }, TimeSpan.FromDays(1));
            return result.As<TransportOrderDto>();
        }
        #endregion

        #region 获取运输订单列表
        public IEnumerable<TransportOrderDto> GetList()
        {
            var result = this.redisService.TryGet(key, () =>
            {
                return this.transportOrderData.GetList().GetAwaiter().GetResult();
            }, TimeSpan.FromDays(1));
            return result.As<IEnumerable<TransportOrderDto>>();
        }
        #endregion

        #region 获取运输订单分页
        public PageableList<TransportOrderDto> Query(DateTime? start, DateTime? end, string sortName, bool? ascending, int pageIndex, int pageSize)
        {
            string cacheKey = this.redisService.GetKey(key, start, end, sortName, ascending, pageIndex, pageSize);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var data = this.transportOrderData.Query(start, end, sortName, ascending, pageIndex, pageSize).GetAwaiter().GetResult();
                return new PageableList<TransportOrderDto>
                {
                    Count = data.Item2,
                    Items = data.Item1.As<IEnumerable<TransportOrderDto>>(),
                    PageIndex = pageIndex,
                    PageSize = pageSize,
                    ServerTime = DateTime.Now
                };
            }, TimeSpan.FromMinutes(30));

            return result;
        }
        #endregion
    }
}